package com.sxu.threadpool;

import java.util.HashSet;
import java.util.concurrent.TimeUnit;

/**
 * 线程池
 */
public class MyThreadPool {
    // 阻塞队列
    private MyBlockingQueue<Runnable> taskQueue;
    // 线程集合
    private HashSet<Worker> workers = new HashSet();
    // 核心线程数
    private int coreSize;
    // 超时时间
    private long timeout;
    // 时间单位
    private TimeUnit timeUnit;
    // 拒绝策略
    private RejectPolicy<Runnable> rejectPolicy;


    // 构造方法
    public MyThreadPool(int coreSize, long timeout, TimeUnit timeUnit, int queueCapacity, RejectPolicy<Runnable> rejectPolicy) {
        this.coreSize = coreSize;
        this.timeout = timeout;
        this.timeUnit = timeUnit;
        this.taskQueue = new MyBlockingQueue<>(queueCapacity);
        this.rejectPolicy = rejectPolicy;
    }

    // 执行任务
    public void execute(Runnable task) {
        // 任务数 < 核心线程数 直接交给worker执行
        // 任务数 >= 核心线程数 加入任务队列等待
        synchronized (workers) {
            if(workers.size() < coreSize) {
                Worker worker = new Worker(task);
                System.out.println("新增work" + worker + task);
                // 加入线程
                workers.add(worker);
                worker.start();
            } else{
                /*
                * 情况：
                *   死等
                *   带超时时间的阻塞等待
                *   主线程放弃任务的执行
                *   抛出异常
                *   调用者自己执行任务
                * 使用策略设计模式，将具体实现交给调用者决定
                * */
                //taskQueue.put(task);
                // taskQueue.offer(task, timeout, timeUnit);
                taskQueue.tryPut(rejectPolicy, task);
            }
        }
    }

    // Thread类内容优先，将其包装成worker类
    class Worker extends Thread {
        private Runnable task;
        public Worker(Runnable task) {
            this.task = task;
        }
        @Override
        public void run() {
            /*
             * 执行任务
             *   task不为空 执行当前任务
             *   task为空 从taskQueue中获取任务再执行
             * */
            while(task != null || (task = taskQueue.poll(timeout,timeUnit))!=null){
                try{
                    System.out.println("正在执行" + task);
                    task.run();
                } catch(Exception e){
                    e.printStackTrace();
                } finally {
                    task = null;
                }
            }
            synchronized (workers) {
                System.out.println("移除worker" + this);
                workers.remove(this);
            }
        }
    }
}